﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace OutOfUnity
{
    class Ringbuffer
    {
        uint readPos_ = 0;
        uint writePos_ = 0;
        uint maxSize_ = 0;
        uint count_ = 0;
        byte[] data_;

        public Ringbuffer(uint size)
        {
            data_ = new byte[size];
            maxSize_ = size;
        }

        public uint read(byte[] buf, uint length)
        {
            var size = count_ > length ? length : count_;
            for (uint i = 0; i < size; i++)
            {
                buf[i] = data_[readPos_];
                readPos_ = (readPos_ + 1) % maxSize_;
            }
            count_ -= size;
            return size;
        }

        public uint write(byte[] buf, uint length)
        {
            var size = (((maxSize_ - count_) > length) ? length : maxSize_ - count_);
            for (uint i = 0; i < size; i++)
            {
                data_[writePos_] = buf[i];
                writePos_ = (writePos_ + 1) % maxSize_;
            }
            count_ += size;
            return size;
        }

        public uint copy(byte[] buf, uint length)
        {
            var size = count_ > length ? length : count_;
            var temp_read_pos = readPos_;
            for (uint i = 0; i < size; i++)
            {
                buf[i] = data_[temp_read_pos];
                temp_read_pos = (temp_read_pos + 1) % maxSize_;
            }
            return size;
        }

        public uint eat(uint length)
        {
            var size = count_ > length ? length : count_;
            for (uint i = 0; i < size; i++)
            {
                readPos_ = (readPos_ + 1) % maxSize_;
            }
            count_ -= size;
            return size;
        }

        public uint available()
        {
            return count_;
        }
    }
}
